/*******************************************************************************
 * Copyright (c) 2002 Boris Pruessmann and others. All rights reserved. This
 * program and the accompanying materials are made available under the terms of
 * the Common Public License v0.5 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors: Boris Pruessmann - Initial implementation.
 ******************************************************************************/
package net.sourceforge.perforce.ui.action;

import net.sourceforge.perforce.core.PerforceException;
import net.sourceforge.perforce.core.api.IPerforceServer;
import net.sourceforge.perforce.core.api.IResolveResult;
import net.sourceforge.perforce.core.api.ResolveTypeEnum;
import net.sourceforge.perforce.core.internal.P4TeamProvider;
import net.sourceforge.perforce.core.resources.IP4File;
import net.sourceforge.perforce.core.resources.RemoteResource;
import net.sourceforge.perforce.ui.P4ResolveEditorInput;
import net.sourceforge.perforce.ui.PerforceCompareEditorInput;
import net.sourceforge.perforce.ui.PerforceResourceEditionNode;
import net.sourceforge.perforce.ui.PerforceResourceNode;
import net.sourceforge.perforce.ui.PerforceUIPlugin;
import net.sourceforge.perforce.ui.internal.Policy;

import org.eclipse.compare.CompareEditorInput;
import org.eclipse.compare.CompareUI;
import org.eclipse.compare.internal.CompareUIPlugin;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.action.IAction;
import org.eclipse.swt.widgets.Display;
import org.eclipse.team.core.TeamException;

/**
 * @version $Revision: 488 $
 * @author <a href="mailto:bpruessmann@users.sourceforge.net">Boris
 *         Pruessmann</a>
 */
public class ResolveManuallyAction extends P4FileAction {
  //----------------------------------------------------------------------------
  // -- Public Methods

  @Override
  public void run(IAction action) {
    try {
      triggerCompareUI();

      IP4File[] files = getSelectedPerforceFiles();
      Policy.assertTrue(files.length == 1);

      IWorkspaceRoot root = PerforceUIPlugin.getWorkspace().getRoot();
      IFile file = root.getFileForLocation(files[0].getLocation());
      if (!file.isSynchronized(IResource.DEPTH_INFINITE)) {
        file.refreshLocal(IResource.DEPTH_INFINITE, null);
      }

      IPerforceServer server = files[0].getServer();

      // Get Ancestor
      RemoteResource ancestorResource = getAncestor(file, server);
      Policy.assertNotNull(ancestorResource);

      // Get Remote
      P4TeamProvider provider = P4TeamProvider.getProvider(file);
      RemoteResource remoteResource = provider.getRemoteTree(file, "#head", null);

      PerforceCompareEditorInput input =
          new P4ResolveEditorInput(new PerforceResourceNode(file), new PerforceResourceEditionNode(
              remoteResource), new PerforceResourceEditionNode(ancestorResource));

      openCompareEditor(input);
    } catch (TeamException e) {
      handle(e);
    } catch (CoreException e) {
      handle(e);
    }
  }

  // ---------------------------------------------------------------------------
  // Protected Methods

  @SuppressWarnings("unused")
  // PerforceException
  @Override
  protected boolean isEnabled() throws PerforceException {
    IP4File[] files = getSelectedPerforceFiles();
    if (files.length != 1) {
      return false;
    }

    IP4File file = files[0];
    if (!file.needsResolve()) {
      return false;
    }

    IWorkspaceRoot root = PerforceUIPlugin.getWorkspace().getRoot();
    IFile eclipseFile = root.getFileForLocation(file.getLocation());
    if (eclipseFile == null || !eclipseFile.isAccessible()) {
      return false;
    }

    return true;
  }

  //----------------------------------------------------------------------------
  // - Private Methods

  /**
   * Called to retrieve the ancestor resource for the given file.
   * 
   * @param file the file.
   * @param server the perforce server.
   * @return the ancestor resource.
   * 
   * @throws TeamException in case of an error.
   */
  private RemoteResource getAncestor(IFile file, IPerforceServer server) throws TeamException {
    P4TeamProvider provider = P4TeamProvider.getProvider(file);
    IResolveResult[] resolveResults =
        server.resolve(file.getLocation().toOSString(), ResolveTypeEnum.AUTOMATIC,
            IPerforceServer.RESOLVE_SIMULATE);
    Policy.assertTrue(resolveResults.length == 1);

    int revision = resolveResults[0].getRevision().intValue() - 1;
    RemoteResource result = provider.getRemoteTree(file, "#" + revision, null); //$NON-NLS-1$

    return result;
  }

  /**
   * Called to open the Compare Editor UI with the given input.
   * 
   * @param input the input.
   */
  private void openCompareEditor(final CompareEditorInput input) {
    Runnable runnable = new Runnable() {
      public void run() {
        CompareUI.openCompareEditor(input);
      }
    };

    Display display = getShell().getDisplay();
    display.syncExec(runnable);
  }

  /**
   * This method will trigger the load of the Compare Component within the
   * display thread
   */
  private void triggerCompareUI() {
    Display display = getShell().getDisplay();
    display.syncExec(new Runnable() {
      /** @see java.lang.Runnable#run() */
      public void run() {
        CompareUIPlugin.getDefault();
      }
    });
  }
}
